#include <iostream>
#include <unistd.h>
#include <stdlib.h>
#include "task.hpp"
#include "channel.hpp"
#include <sys/wait.h>

void Usage(std::string proc)
{
    std::cout << "Usage: " << proc << " process-num" << std::endl;
}

void Worker()
{
    while (true)
    {
        unsigned int num = 0;
        int i = ::read(0, &num, sizeof(num));
        if (i == sizeof(num))
        {
            std::cout << "######################" << std::endl;
            ts.Excute(num);
        }
        else if (i == 0)
        {
            std::cout << "pid: " << getpid() << " quit..." << std::endl;
            break;
        }
    }
}

void debugprint(std::vector<Channel> Channels)
{
    for (auto &c : Channels)
    {
        std::cout << c.name() << std::endl;
    }
}

int main(int argc, char *argv[])
{
    if (argc < 2)
    {
        Usage(argv[0]);
        return 0;
    }
    int nums = std::stoi(argv[1]);
    // 1. 初始化进程池
    std::vector<Channel> Channels;
    for (int i = 0; i < nums; i++)
    {
        int pipefd[2] = {0};
        int pi = pipe(pipefd);
        if (pi == -1)
        {
            std::cout << "pipe error" << std::endl;
            return 1;
        }
        pid_t id = fork();
        if (id < 0)
        {
            std::cout << "fork error" << std::endl;
            return 2;
        }
        else if (id == 0)
        {
            for(auto& c: Channels)
            {
                close(c.fd());//子进程每次继承都会父进程的写接口，故需要我们手动关闭
            }
            ::close(pipefd[1]);
            dup2(pipefd[0], 0);
            Worker();
            ::exit(0);
        }
        // else{}(父进程判不判断都可以，因父进程和子进程是并发执行的)
        // 父进程任务
        ::close(pipefd[0]);
        Channels.emplace_back(pipefd[1], id);
        //...
    }
    // 2. 派发任务
    int who = 0;
    int num = 20;
    while (num--)
    {
        int task = ts.SelectTask();
        Channel &curr = Channels[who++];
        who %= Channels.size();
        std::cout << "######################" << std::endl;
        std::cout << "send " << task << " to " << curr.name() << ", 任务还剩: " << num + 1 << std::endl;
        curr.send(task);
        sleep(1); // 不在子进程休眠原因是为了避免父进程退出了，子进程还在执行任务
                  // 倘若在子进程休眠父进程则会早早写完（write）退出
    }

    // 3. 退出进程池
    for (auto &c : Channels)
    {
        close(c.fd());
        pid_t rid = waitpid(c.id(), nullptr, 0);
        if (rid > 0)
        {
            std::cout << "等待进程：" << rid << "sucess" << std::endl;
        }
    }
    // for(auto& c: Channels)
    // {
    //     close(c.fd());
    // }
    // for(auto& c:Channels)
    // {
    //     pid_t rid = waitpid(c.id(), nullptr, 0);
    //     if(rid > 0)
    //     {
    //         std::cout << "等待进程：" << rid << "sucess" << std::endl;
    //     }
    // }
}